
package com.jcode.netty.codec;

import java.io.Serializable;
import java.nio.ByteBuffer;

import com.jcode.netty.protocol.Packet;
import com.jcode.netty.serialize.FastJsonSerializer;
import com.jcode.netty.serialize.Serializer;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;

/**
 * @Desc
 * @Author dreajay
 * @DateTime 2016年11月17日 下午8:40:13
 */
public final class NettyEncoder extends MessageToByteEncoder<Packet> {

    private Serializer serializer;

    private Serializer fastJsonSerializer = new FastJsonSerializer();

    public NettyEncoder(Serializer serializer) {
        this.serializer = serializer;
    }

    @Override
    protected void encode(ChannelHandlerContext ctx, Packet packet, ByteBuf out) throws Exception {
        if (packet == null) {
            throw new Exception("The encode packet is null");
        }
        out.writeBytes(encode(packet));
    }

    public ByteBuffer encode(Packet packet) throws Exception {
        // 报文总长度
        int length = 0;
        // 报文头长度 4
        length += 4;
        byte[] headerData = fastJsonSerializer.serialize(packet);
        // 报文头内容长度
        length += headerData.length;
        Serializable body = packet.getBody();
        if (body != null) {
            byte[] bodyData = serializer.serialize(body);
            packet.setBodyData(bodyData);
            // 报文体内容长度
            length += bodyData.length;
        }

        // 报文长度=4个字节长度标示+报文总长度
        ByteBuffer result = ByteBuffer.allocate(4 + length);
        // 报文长度标示
        result.putInt(length);
        // 报文头长度
        result.putInt(headerData.length);
        // 报文头内容
        result.put(headerData);
        if (body != null) {
            // 报文体内容
            result.put(packet.getBodyData());
        }
        result.flip();
        return result;
    }

}
